Skip to content

v3: framework-agnostic deploy pipeline + standalone service clients#1255

Open
Huijiro wants to merge 166 commits intomainfrom
v3
Open

v3: framework-agnostic deploy pipeline + standalone service clients#1255
Huijiro wants to merge 166 commits intomainfrom
v3

Conversation

@Huijiro
Copy link
Copy Markdown
Member

@Huijiro Huijiro commented Mar 23, 2026

What changes

This is the v3 line of the Agentuity SDK. It removes the bundled @agentuity/runtime "agent runtime" model and replaces it with a framework-agnostic deploy pipeline plus a set of standalone service-client packages.

You bring your framework (Next.js, Hono, SvelteKit, Astro, Nuxt, Remix, Vite + React, …); we provide the build and deploy infrastructure plus the service clients you call directly from your code.

Currently published as 3.0.0-beta.0 on the beta npm tag.

bun add @agentuity/cli@beta
# or
npm install -g @agentuity/cli@beta

Architecture

Buildpack-based deploy pipeline

  • Framework detection engine (25 frameworks recognised) → build adapters → CNB packaging (launch.json + Procfile).
  • agentuity dev is a passthrough to the framework's own dev script with AI Gateway env injection (OPENAI_API_KEY / OPENAI_BASE_URL etc. routed through the gateway when AGENTUITY_SDK_KEY is set).
  • agentuity deploy works against any project the buildpack knows how to build — no Agentuity-specific config, no agentuity.config.ts.
  • CDN assets handled per framework via staticDir; static server injected when no start command exists.

Framework scaffolding (agentuity project create)

  • Runs the official CLI for the chosen framework.
  • Overlays an AI translation demo (/translate endpoint + landing page using the AI SDK).
  • Adds @agentuity/cli as a devDependency, a deploy script, and .gitignore entries.
  • Service augments (multi-select prompt): each selected augment composes into the existing translate demo via marker-comment splicing. Available augments: DB (drizzle-orm + @neondatabase/serverless), KeyValue, Queue, Storage, Vector. Each one wires real functionality into the demo (cached translations, history, similar-translation search, queued jobs, exports).
  • Detects existing framework projects so the augments flow can run against an already-scaffolded repo.

Service-client packages

Standalone packages that talk directly to Agentuity's Catalyst API. Useable in any framework, in any runtime that supports fetch (Node 24+, Bun 1.3+):

@agentuity/db, @agentuity/email, @agentuity/keyvalue, @agentuity/queue, @agentuity/sandbox, @agentuity/schedule, @agentuity/storage, @agentuity/task, @agentuity/vector, @agentuity/webhook.

import { KeyValueClient } from '@agentuity/keyvalue';

const kv = new KeyValueClient();
await kv.set('namespace', 'key', { value: 'data' }, { ttl: 3600 });
const result = await kv.get('namespace', 'key');

Hono integration

@agentuity/hono ships an agentuity() middleware for projects that prefer the v2-style c.var.* access pattern:

import { Hono } from 'hono';
import { agentuity } from '@agentuity/hono';

const app = new Hono();
app.use('*', agentuity());

app.get('/data', async (c) => {
  const value = await c.var.kv.get('namespace', 'key');
  return c.json(value);
});

export default app;

Migration tool

@agentuity/migrate covers the upgrade path. Auto-detects the source version from package.json, then runs the right migration:

  • ^1.x → v1 → v2
  • ^2.x → v2 → v3 (rewrites createApp/createAgent patterns into a plain Hono app, generates src/services.ts with singleton clients, replaces c.var.*/ctx.* access with direct service-client imports)

Both modes are also force-selectable via --v1-to-v2 / --v2-to-v3.

CLI runtime

The agentuity CLI now runs under both Node 24+ and Bun 1.3+ (was Bun-only). All service-client packages are dual-runtime as well.


Packages

Tooling

  • @agentuity/cli — main CLI
  • create-agentuitybun create agentuity shim that delegates to the CLI
  • @agentuity/coder + @agentuity/coder-tui — Coder Hub (sandbox-as-a-service IDE)
  • @agentuity/vscode — VS Code extension
  • @agentuity/claude-code, @agentuity/opencode — coding-agent integrations

Service clients

@agentuity/db, email, keyvalue, queue, sandbox, schedule, storage, task, vector, webhook

Framework integration

  • @agentuity/hono — Hono middleware
  • @agentuity/migrate — v1 → v2 → v3 migration tooling

Infrastructure (rarely consumed directly)

  • @agentuity/core — shared types, schema interfaces, API client primitives
  • @agentuity/server — server-side helpers used by @agentuity/cli
  • @agentuity/telemetry — OpenTelemetry initialization + JSONL exporters
  • @agentuity/analytics, stream, adapter

Deprecated (still publish; npm deprecated field set)

  • @agentuity/runtime — gutted to a stub. Importing createApp, createAgent, or createRouter throws with a migration message. Will be removed in v3.1.
  • @agentuity/postgres, @agentuity/drizzle — superseded by using drizzle-orm + @neondatabase/serverless directly.
  • @agentuity/schema — superseded by Zod or Valibot.
  • @agentuity/local — local-dev fallback layer; will be removed in v3.1.

Removed

  • @agentuity/auth (BetterAuth integration, core auth types, CLI project auth commands)
  • @agentuity/react, @agentuity/frontend (React hooks, WebRTC managers, transport hooks)
  • @agentuity/workbench
  • @agentuity/evals (eval framework, CLI eval-run commands, core eval services)
  • templates/ directory (no templates tarball in publish)
  • examples/ directory (the v2-style demo apps)

Breaking changes

This is a breaking release. There is no shim layer — @agentuity/migrate is the supported v2 → v3 path.

What changed What to do
createApp() is gone Use your framework's normal entry point. agentuity deploy works with any buildable project.
createAgent() / agent registry is gone Build with your framework; call service clients directly.
bootstrapRuntimeEnv() is gone The migrator strips the import + call.
@agentuity/runtime is a deprecation stub Stop importing from it.
@agentuity/auth removed Use BetterAuth or any other auth library directly.
@agentuity/react / @agentuity/frontend removed Use the framework's own state and transport primitives.
agentuity.config.ts deprecated Migration handles it.
CLI requires Node 24+ or Bun 1.3+ Check the runtime versions in your CI.

Testing

  • tests/services/<svc>/ — standalone Bun apps that hit the live cloud per service client.
  • tests/frameworks/{tanstack-start,nextjs-app,svelte-web} — Playwright e2e against the buildpack pipeline + AI Gateway translation flow.
  • tests/integration/{e2e-web,oauth,standalone-backend} — minimal Hono apps used as integration targets.
  • Unit tests live alongside each package in packages/<pkg>/test/.

CI status: Build Packages & Test, Package Smoke Test, NPM Pack & Upload, Test Install Script, Biome, and Windows WSL CLI Test all green on the latest commit. The Service Client Smoke Tests DB step is currently gated behind agentuity/infra#120 (SDK keys can't authenticate against the DB /resource endpoints — being addressed platform-side).


Install

# CLI
bun add @agentuity/cli@beta
npm install -g @agentuity/cli@beta

# Service clients
bun add @agentuity/keyvalue@beta @agentuity/queue@beta @agentuity/vector@beta

The beta dist-tag points at 3.0.0-beta.0 today and will move forward as v3 stabilises. The latest dist-tag remains on the v2 line until v3 is promoted.

Huijiro and others added 30 commits March 10, 2026 14:39
…ead AST code

- Workbench schema endpoint now generates TypeScript interface syntax
  from JSON Schema (via runtime toJSONSchema) instead of requiring
  Zod source strings from the AST-extracted metadata. Falls back to
  metadata strings only when no runtime schema is available.

- Add jsonSchemaToTypeScript() utility in workbench.ts that converts
  JSON Schema → clean TypeScript type notation for display:
  { name: string; age: number; tags?: string[] }

- Delete findCreateAppEndPosition() from ast.ts — dead code, exported
  but never imported anywhere.

- 20 new tests covering all JSON Schema → TypeScript conversions:
  primitives, objects, optionals, descriptions, arrays, unions,
  intersections, enums, literals, nullables, records, nested objects.
…hemaToTypeScript

Address CodeRabbit review feedback:
- Escape quotes, backslashes, and newlines in const/enum string values
- Quote property keys that aren't valid JS identifiers (hyphens, spaces, leading digits)
- 3 new test cases covering both fixes
Remove 402 lines of dead code from the AST pipeline:

- Delete analyzeWorkbench() + parseConfigObject() — only imported by
  the dead workbench.ts file, never used in production
- Delete checkFunctionUsage() — exported but never imported anywhere
- Delete checkRouteConflicts() — exported but never imported anywhere
- Delete WorkbenchAnalysis interface — only used by dead code
- Remove WorkbenchConfig import from ast.ts (no longer needed)
- Delete packages/cli/src/cmd/build/workbench.ts entirely — the whole
  file was dead code (getWorkbench, generateWorkbenchMainTsx, etc.
  are superseded by vite/workbench-generator.ts)
- Remove analyzeWorkbench tests from ast.test.ts (testing dead code)

ast.ts: 3,526 → 3,124 lines (402 lines removed, cumulative with
previous findCreateAppEndPosition deletion)
The lifecycle generator now uses TypeScript's own type checker to
extract the setup() return type instead of walking AST literals and
guessing types from values. This handles:

- Inline setup in createApp({ setup: () => ... })
- Exported setup functions (function decl or const arrow)
- Shorthand property: createApp({ setup })
- Variable references: setup: () => someVar
- Async functions (Promise unwrapping)
- Any pattern TypeScript itself can resolve

Also extract getDevmodeDeploymentId into ids.ts (pure hash, not AST).

ast.ts consumers remaining: only parseRoute (route-discovery.ts)
…iscovery + app-router-detector

createRouter() no longer wraps Hono methods — it's now just `new Hono()`
with Agentuity's Env type. This preserves Hono's full Schema type inference
chain, enabling `typeof router` to encode all route types.

The routeId lookup (for OTel spans) and returnResponse auto-conversion that
createRouter previously did will move to entry-file middleware in a follow-up.

agent-discovery.ts: rewritten to import() agent files at build time instead
of AST-parsing with acorn-loose. The agent instance already knows its own
metadata, schemas, and evals. Schemas are now extracted as JSON Schema
strings via toJSONSchema() instead of Zod source strings via astring.

app-router-detector.ts: rewritten to use TypeScript's compiler API instead
of acorn-loose. Detects createApp({ router }) patterns for explicit routing.

Both rewrites eliminate acorn-loose/astring usage from their respective files.
Only ast.ts itself still imports acorn-loose (for parseRoute, used by
route-discovery.ts).

Tests: 18 agent-discovery tests, 8 app-router-detector tests, 8 lifecycle
tests, dev-registry-generation tests all pass. Runtime: 665 tests pass.
- Delete ast.ts (3,120 lines) — entire acorn-loose + astring AST pipeline
- Delete route-migration.ts (793 lines) — file-based routing migration
- Delete api-mount-path.ts (87 lines) — file-based path computation
- Remove acorn-loose + astring from package.json
- Remove file-based routing fallback from entry-generator.ts
- Remove migration prompts from dev/index.ts and vite-bundler.ts
- Remove src/api/ directory watcher from file-watcher.ts
- Remove migrateRoutes CLI option
- Delete 15 test files testing deleted AST/file-based routing code
- Rewrite route-discovery + dev-registry tests for new architecture

Net: -13,073 lines deleted, +199 lines added
- Import toForwardSlash from normalize-path.ts instead of duplicating
- Replace existsSync with Bun.file().exists() in lifecycle-generator,
  app-router-detector, and agent-discovery
- Import toJSONSchema from @agentuity/schema public entry point (resolved
  from user's node_modules) instead of reaching into src/ internals
- Remove createAgent substring gate — check exported value shape instead,
  supporting re-exported agents
- Default createRouter S generic to BlankSchema ({}) to match Hono 4.7.13
- Migrate integration-suite, e2e-web, svelte-web, auth-package-app,
  webrtc-test, nextjs-app, tanstack-start, vite-rsc-app to explicit
  createApp({ router }) pattern
- Create combined router.ts files for apps with multiple route files
- Expose agent.evals on AgentRunner (was missing, breaking eval discovery)
- Deduplicate agents by name (re-exported agents from index.ts)
- Update route-metadata-nested tests for explicit routing
…estart loop

- Runtime: createApp() returns fetch/port/hostname for bun --hot to
  hot-swap the server's request handler without process restart
- Runtime: skip Bun.serve() in dev mode (bun --hot manages server
  via default export)
- Runtime: add idempotent OTel re-registration guard for hot reloads
- Runtime: pass cors/compression config directly to middleware instead
  of lazy global lookup via getAppConfig()
- Runtime: remove getAppState/getAppConfig/setAppConfig globals
  (config passed directly, app state was always {})
- Runtime: add typed _globals.ts for Symbol.for() state and globals.d.ts
  for string-keyed globalThis properties, eliminating unsafe casts
- Runtime: use Symbol.for() pattern in _process-protection.ts
- Runtime: guard one-time log messages (server started, local services)
  to prevent reprinting on hot reloads
- Runtime: downgrade internal port messages to debug level
- CLI: use bun --hot --no-clear-screen for backend subprocess
- CLI: remove file-watcher.ts usage, restart loop, stopBunServer,
  cleanupForRestart — bun --hot handles all backend HMR
- CLI: run 'Preparing dev server' once at startup instead of on
  every file change (~490 lines removed from dev/index.ts)
In production mode, startServer() already calls Bun.serve() on the
configured port. Bun v1.2+ also auto-serves when the default export
has fetch + port properties (added in c98ce19 for --hot support),
causing a second bind attempt and EADDRINUSE.

Strip fetch/port/hostname from the returned AppResult in production
so only the explicit Bun.serve() is active. Dev mode keeps them for
bun --hot auto-serve.
Resolve conflicts:
- modify/delete: keep v2's deletions of generated files (app.ts, routes.ts),
  ast.ts, and route-migration.ts — superseded by v2's import-based architecture
- agent-discovery.ts: keep v2's import-based version, port duplicate eval name
  detection from main (cab51e2)
- dev/index.ts: keep v2's bun --hot version — main's file-watcher restart loop
  fixes (5b7f9b8) don't apply since v2 removed the restart loop

Auto-merged from main:
- Gateway URL fallback update (agentuity.ai → catalyst.agentuity.cloud)
- Windows path fix for AI SDK patches (buildPatchFilter)
- Task status aliases, sandbox events, OIDC commands, monitoring
- Coder TUI updates, API reference docs, various CLI fixes
Bun --hot creates the server from the default export's properties.
Without the websocket handler, WebSocket upgrades fail with:
'To enable websocket support, set the "websocket" object in Bun.serve({})'

Add websocket from hono/bun to the AppResult (and strip it in
production alongside fetch/port/hostname).
json5 was not declared as a dependency in cli/package.json, causing
a type error. Use the existing parseJSONC utility (from utils/jsonc)
which handles tsconfig.json comments and trailing commas.
## @agentuity/migrate package (new)

A CLI tool to migrate v1 projects to v2:
- `npx @agentuity/migrate` — guided migration with codemods
- Deletes `src/generated/` directory
- Removes `bootstrapRuntimeEnv()` call from app.ts
- Transforms routes from createRouter() mutable style to new Hono<Env>() chained
- Generates src/api/index.ts and src/agent/index.ts barrels
- Adds migration comments for setup/shutdown lifecycle
- Guides on agentuity.config.ts deprecation
- Detects frontend using removed APIs (createClient, useAPI, RPCRouteRegistry)
- Runs bun install and typecheck post-migration

## agentuity.config.ts deprecation

- New app-config-extractor.ts extracts analytics/workbench from createApp()
- config-loader.ts emits deprecation warning when loading agentuity.config.ts
- getWorkbenchConfig() now prefers runtime config from createApp()
- dev/index.ts and vite-builder.ts use loadRuntimeConfig()

Config consolidation in v2:
- Runtime config (analytics, workbench, cors, etc.) → createApp() only
- Vite config (plugins, define, render, bundle) → vite.config.ts
- agentuity.config.ts → deprecated, delete entirely

## Documentation

- Updated migration-guide.mdx with v1→v2 tab
- Includes automated migration instructions and manual steps
- Covers all breaking changes and troubleshooting
This commit consolidates several v2 improvements:

### bun-dev-server error diagnostics
- Add app.ts validation to detect v1 pattern (destructuring without export default)
- Capture Bun stderr/stdout and show in error messages
- Add port cleanup with ensurePortAvailable() to kill orphan processes
- Warn before starting if app.ts has common issues
- Export validation functions for testing

### Process manager for dev mode
- New ProcessManager class to track all spawned processes/servers
- Ordered cleanup (LIFO for processes)
- Force kill fallback after timeout
- Integrated into dev/index.ts for cleanup on failure/shutdown

### Remove agentuity.config.ts support
- Deleted loadAgentuityConfig from config-loader.ts
- getWorkbenchConfig now only takes (dev, runtimeConfig) - no config file fallback
- Users must use vite.config.ts for Vite config
- Users must use createApp() for runtime config (workbench, analytics)

### Remove auto-adding React plugin
- Vite no longer auto-adds @vitejs/plugin-react
- Users must configure frontend framework in vite.config.ts

### Deprecate @agentuity/react
- Added deprecation notice to README.md and package.json
- @agentuity/auth no longer depends on @agentuity/react
- AuthProvider now accepts callback props instead of relying on AgentuityProvider

### Migrate tool updates
- Detect missing vite.config.ts when frontend exists
- Detect deprecated @agentuity/react API usage
- Detect agentuity.config.ts and suggest migration

Tests: Updated workbench tests, removed define-config test (obsolete), added process-manager tests
Tests verify:
- publicDir is set correctly in dev mode config
- Public files are served at root paths in dev
- Public files maintain directory structure
- Various file types are handled correctly
- Edge cases (empty folder, hidden files, subdirectories)
- Integration with vite-builder functions
Add tests for dev server orchestration covering:

- dev-lock.test.ts: Lockfile management, orphan process cleanup,
  edge cases for corrupted/missing lockfiles

- ws-proxy.test.ts: Front-door TCP proxy routing decisions,
  error handling, URL parsing, query strings

- dev-server-integration.test.ts: Full lifecycle testing,
  crash recovery, hot reload validation, error resilience

All 60 tests pass covering:
- Startup/shutdown with port cleanup
- Hot reload behavior (Bun --hot, Vite HMR)
- Crash recovery (SIGTERM/SIGKILL escalation)
- WS proxy routing (HTTP→Vite, WS upgrade→Bun)
- Error resilience (TypeScript errors, v1 patterns)
Merge main (1.0.54) into v2 branch.

Resolution strategy:
- Deleted files (v2): Kept v2's removal of src/generated/*, ast.ts, route-migration.ts
- Dev server files: Kept v2's no-bundle architecture with bun --hot
- Package versions: Took main's higher versions
- New features from main: Accepted (oauth, sandbox jobs, service packages)
- API docs: Took main's updated documentation

Key changes merged from main:
- New standalone service packages (@agentuity/db, @agentuity/email, etc.)
- OAuth service support
- Sandbox job commands
- Updated CLI commands for all cloud services
- API reference documentation updates
Since React is no longer auto-added by the CLI, each project with a
frontend needs its own vite.config.ts with the appropriate plugins.

Added vite.config.ts for:
- apps/docs (React + Tailwind + MDX + TanStack Router)
- apps/testing/e2e-web (React)
- apps/testing/cloud-deployment (React)
- apps/testing/integration-suite (React)
- apps/testing/auth-package-app (React)
- apps/testing/oauth (React)
- apps/testing/webrtc-test (React)
- apps/testing/svelte-web (Svelte - pending investigation for CLI build)

Updated vite-builder.ts to properly merge user vite.config.ts:
- User plugins now come FIRST (important for framework plugins like Svelte)
- User config values are preserved unless overridden by Agentuity-specific needs
- Removed mergeConfig in favor of explicit spread to avoid array merge issues

Note: Svelte builds work with vite v8.0.1 building client environment for production...
�[2K
transforming...✓ 1 modules transformed. but fail when built
through the CLI. This requires further investigation into how the
Svelte plugin interacts with the CLI's build process.
…lity

## Problem
Svelte 5 builds failed when invoked through CLI's programmatic viteBuild()
call, but worked correctly with `bunx vite build`. The error showed the
Svelte compile plugin receiving already-compiled JavaScript instead of
Svelte source code.

## Root Cause
Bun's module loading system has issues with Vite's plugin pipeline when
importing Vite and calling build() programmatically. Certain plugins like
@sveltejs/vite-plugin-svelte receive already-compiled code, possibly due to
module state caching or transformation order issues.

## Solution
For client builds, spawn `bun x vite build` as a subprocess instead of
importing Vite and calling build() programmatically. This gives Vite complete
control over its module loading and plugin execution, avoiding Bun's
module system entirely.

Workbench builds continue using programmatic viteBuild() since those use
our own React plugin without external framework plugins.

## Additional Changes
- Updated vite.config.ts for all test projects to include root and input
  path (required when spawning vite as subprocess)
- Updated svelte-web agentuity.config.ts to v2 format (removed plugins)
- Removed temporary svelte.config.js that was added during debugging

## Testing
All test projects now build successfully:
- apps/testing/e2e-web (React)
- apps/testing/svelte-web (Svelte 5)
- apps/testing/cloud-deployment (React)
- apps/testing/integration-suite (React)
- apps/testing/auth-package-app (React)
- apps/testing/oauth (React)
- apps/testing/webrtc-test (React)
The migrate package was missing from the root tsconfig.json references,
causing it to not be built during CI builds.
The evals package depends on @agentuity/runtime and @agentuity/schema
but was missing the TypeScript project references, causing build failures.
Since the CLI now spawns vite as a subprocess for client builds,
projects need a vite.config.ts file with the proper input path.

Added:
- templates/_base/vite.config.ts with React plugin and input path
- vite and @vitejs/plugin-react to devDependencies in package.json
When vite.config.ts sets root='.' and input='src/web/index.html',
vite outputs the HTML at client/src/web/index.html instead of
client/index.html. The runtime now checks both locations.

This fixes cloud deployment tests that were failing because
the analytics beacon injection couldn't find the HTML file.
Huijiro added 9 commits May 5, 2026 12:16
…test

The db client smoke test (tests/services/db/index.ts) needs both env
vars to talk to a real provisioned database. Previously the workflow
only set AGENTUITY_SDK_KEY, so the test fell back to placeholder
'test-org' / 'testdb' values and got 401 Unauthorized from the API.

AGENTUITY_ORG_ID is sourced from the repo secret of the same name;
the database name is hardcoded to 'testdb' (the test db pre-created
on the integration-suite org).
testdb is provisioned in region 'use' on the Agentuity Testing org,
but the workflow defaults AGENTUITY_REGION to 'usc'. The DB API path
/resource/<orgId>/<region>/<database>/tables fails auth when the
(orgId, region, database) triple doesn't resolve to a real resource,
which surfaced as 'Unauthorized'.

Override AGENTUITY_REGION=use on just the db step so the other
services (which live in usc) aren't affected.
Project-scoped AGENTUITY_SDK_KEY tokens can't authenticate against
the DB /resource/<orgId>/<region>/<database>/... endpoints — only
user/CLI tokens (ck_live_...) work. This makes the documented
@agentuity/db usage pattern unusable from any deployed agent and
blocks the smoke test from passing.

Filed in agentuity/infra#120. Gating the step off with 'if: false'
so the rest of the suite can go green; env vars kept wired so the
test re-enables cleanly once SDK-key DB auth lands.
The smoke test was using `client.create()` with no runtime arg,
which provisions `base:latest` — a shell-only image. The subsequent
`node -e ...` commands exit 127 ("command not found") and the
follow-up `createJob` returns an opaque 500.

Switch to `runtime: 'node:lts'`. Backend error-message quality
tracked separately in agentuity/infra#121.
…side breakage

Adds an .agents/skills/file-infra-issue skill that gates on:
- the issue being clearly infra (not SDK), confirmed via raw curl repro
- duplicate search across open + closed + component-scoped queries
- a tight issue body template (problem / repro / want / why / refs)

Modeled after how we filed agentuity/infra#120 and #121 during the
v3 service smoke test triage. Includes anti-patterns (don't file SDK
bugs, don't pad bodies, mask tokens, no urgency framing) and a
loop-back step to leave SDK-side comments pointing at the issue.
Bump all packages from 3.0.0-alpha.7 to 3.0.0-beta.0 to match the
just-published versions on npm. Workspace dependencies stay as
workspace:* — only the version field changed in each package.json,
plus the matching version entries in .claude-plugin/marketplace.json
and packages/claude-code/.claude-plugin/plugin.json.

Tag: v3.0.0-beta.0
GitHub release: https://github.com/agentuity/sdk/releases/tag/v3.0.0-beta.0
npm dist-tag: beta
Two follow-ups from the 3.0.0-beta.0 cut:

1. `gh release create` was defaulting to the repo's default branch
   (main), so the v3.0.0-beta.0 tag landed on main HEAD instead of
   the v3 commit being published. Pass --target $(git rev-parse HEAD)
   so the release/tag pin to the current commit regardless of branch.

2. The script previously left the working tree dirty after a
   successful publish — versions were bumped on disk and bun.lock
   regenerated, but never committed. Add a commitReleaseChanges()
   step after the post-publish bun install that stages the version
   bumps + lockfile and commits them as 'Release X.Y.Z'. Pushing is
   intentionally left to the operator so they can retarget the tag
   or pull additional changes before pushing.

Globs in the git add path live in literal template strings (not
interpolated via ${...}) because Bun's $ single-quotes interpolated
values, which would defeat pathspec expansion.
- Delete PLAN.md (Service Augments plan — fully implemented in #1445).
- packages/cli/src/cmd/node-compat/crypto.ts: replace dead reference to
  PLAN.md §8 with the actual cache-invalidation note inline.
Sweep through the project's README/AGENTS.md surface and the CLI's
ai-prompt files removing references to packages and APIs that no
longer exist on v3:

Deletions
- packages/cli/src/runtime-bootstrap.md — documented a v2-only
  bootstrapRuntimeEnv() flow that v3 doesn't have.
- packages/cli/src/cmd/ai/prompt/{api,web}.{md,ts} — ~700 lines of
  v2 docs (createRouter, createApp, @agentuity/react, @agentuity/frontend)
  shipped to LLMs via 'agentuity ai prompt api|web'. Drop the
  subcommands; 'agentuity ai prompt llm' (the generic CLI usage guide)
  stays.

Edits
- README.md (root): npm badge points at @agentuity/cli (was /runtime).
  Skills table reflects current skill set. Package structure list
  rebuilt from the actual packages/ directory and grouped by role
  (Tooling / Service clients / Framework integration / Internal /
  Deprecated).
- packages/core/README.md: drop @agentuity/runtime + @agentuity/react
  framing, mention service-client packages instead.
- packages/server/README.md + AGENTS.md: drop 'shared with @agentuity
  /runtime' framing and the deleted api/{apikey,db,eval,queue,session,
  thread} dirs from the structure tree. Note bootstrapRuntimeEnv() is
  a legacy helper with no v3 callers.
- packages/postgres/README.md + AGENTS.md: drop @agentuity/runtime
  shutdown-hook section + createApp() example. Replace with a manual
  shutdownAll() pattern.
- packages/drizzle/README.md + AGENTS.md: drop @agentuity/auth +
  drizzleAdapter sections (auth was deleted; package no longer
  re-exports drizzleAdapter from better-auth).
- packages/create-agentuity/README.md: full rewrite. The package is
  now a thin shim around 'agentuity project create'; the README
  describes the v3 framework-agnostic flow + service augments.
- packages/telemetry/src/exporters/README.md: replace registerOtel
  example (path doesn't exist) with the auto-init pattern + manual
  registerTelemetry() usage.

Typecheck and lint clean.
@Huijiro Huijiro changed the title refactor: middleware architecture for v3 - composable packages v3: framework-agnostic deploy pipeline + standalone service clients May 5, 2026
Huijiro added 16 commits May 5, 2026 15:30
- packages/cli/README.md: drop 'Bun-native' framing, list both Bun
  and Node 24+ as supported, drop the dead validateRuntime() entry
  from the API list.
- packages/cli/AGENTS.md: remove a duplicated 'Runtime' section
  paragraph (was copy-pasted twice).
- packages/cli/src/cmd/project/remote-import.ts: drop the
  findAgentuityYaml() helper and its call site. v3 doesn't read
  agentuity.yaml anywhere — the function only logged 'Found
  agentuity.yaml in template.' and discarded the parsed config.
  Renumber the remaining workflow steps (4-5-6 instead of 5-6-7)
  and drop the now-unused 'yaml' parseYaml import.
- packages/core/src/env.d.ts: remove AGENTUITY_RUNTIME from the env
  type augmentation. It was a v2 'running inside the agent runtime'
  flag and has no setters or readers anywhere in v3.

Typecheck + lint clean.
Adds knip (https://knip.dev/) with a workspace-aware config so we have
a tool for the next round of dead-code cleanup. Run with 'bun run knip'.

The config excludes deferred areas (docs/, examples/, packages/{vscode,
claude-code,opencode,runtime,postgres,drizzle}) since their cleanup is
on a separate timeline (project memories #102 #105 #107 #117 #118).

### File deletions caught by knip

- packages/cli/src/cmd/ai/prompt/version.ts — stranded helper after
  api.ts/web.ts deletion in the previous v2-scrub commit.
- packages/cli/src/cmd/build/patch/{_util,aisdk,index,llm,otel-llm}.ts
  (~800 LOC) — the v2-era build-time AI SDK patcher. v3's AI Gateway
  works via runtime env injection (OPENAI_BASE_URL set when running
  'agentuity dev'), not via AST patching.
- packages/cli/src/cmd/build/ids.ts — getDevmodeDeploymentId() was
  tied to the old gravity-flavored dev mode that was dropped on v3.
- packages/cli/src/node-compat/index.ts — barrel file with no callers
  (we import from individual node-compat/*.ts shims directly).
- packages/coder-tui/src/todo/{index,store,types}.ts — todo store API
  is defined but never called.
- packages/telemetry/src/logger/{index,internal,user}.ts — there are
  TWO logger systems in this package (the file logger.ts which is the
  real one, and the directory logger/ which was older and orphaned).
  Kept logger/console.ts and logger/util.ts, which logger.ts uses.

### Root devDependencies removed

@happy-dom/global-registrator, @testing-library/{dom,jest-dom,react,
react-hooks}, @types/{react,react-dom}, react, react-dom, archiver,
concurrently, jiti, rehype-pretty-code — all left over from deleted
packages (auth, react, frontend, workbench).

### Root dependencies removed

@radix-ui/react-tabs, ai, remark-frontmatter, remark-mdx-frontmatter
— same vintage. The workspace packages that legitimately use 'ai'
already declare it themselves.

bun install removes 17 packages from the lockfile. Typecheck + lint
clean across all 30 packages.

### Caveats / things knip can't see

The packages/core/src/services/<svc>/api-reference.ts files are a
true dependency of docs/scripts/generate-api-reference.ts — they
generate the agentuity.dev API reference docs. The knip config lists
them as entry points so they don't get falsely flagged.

Per-package bun-types and a few other devDep false positives are
left alone; verifying each requires checking tsconfig.test.json
references and is better as a separate pass.
knip cleanup pass.

### packages/cli/src/cmd/ — 134 dead default exports

CLI command files all had pattern:
  export const fooCommand = createCommand({ ... });
  export default fooCommand;

In 134 files the named export is consumed via barrel index.ts
imports (`import { fooCommand } from './foo.ts'`) and the default
export was never imported. Knip flagged each one.

The remaining files (mostly under cmd/cloud/stream/) consume via
`import fooCommand from './foo.ts'` (default), so those defaults
stay.

Stripped via a shell script that walks the knip output and drops
the trailing 'export default <Name>;' line in each flagged file.
Typecheck + lint clean; all 631 CLI unit tests still pass.

### Per-package devDependency cleanup

- Drop bun-types from 14 service-client + helper packages that
  don't reference it in any tsconfig.test.json. @types/bun (which
  every package keeps) declares bun-types as a dep, so the type
  resolution still works transitively.
- Keep bun-types on cli/coder-tui/core/schema/server (those have
  tsconfig.test.json with `types: ["bun-types"]`).
- Drop unused esbuild devDep from packages/core.
- Drop unused @agentuity/test-utils devDep from packages/migrate
  and packages/schema.

### knip config

Add ignoreBinaries (gh, opencode, amp, npm — external CLIs not in
package.json) and ignoreDependencies (@mariozechner/pi-coding-agent
— resolved transitively via @agentuity/coder-tui's deps for the
`require.resolve('.../package.json', ...)` lookup in coder/start.ts).
- packages/cli/src/api.ts: remove getGravityDevModeURL(). Gravity-mode
  dev was dropped on v3 (the v3 'agentuity dev' is a passthrough to
  the framework's own dev script), so no caller resolves a gravity
  devmode URL anymore.
- packages/cli/src/runtime.ts: remove validateGravityRequiresUpgrade()
  and the unused MIN_GRAVITY_VERSION constant. v3 doesn't ship the
  gravity binary; the version-gate check has nowhere to fire.

The 'gravity_url' override in the config schema and the 'gravity'
machine state field stay — those are platform-side data we still
read from APIs, not v2 leftovers.

Caught by knip --no-progress.
The earlier v2 cleanup commit deleted packages/cli/src/cmd/ai/prompt/{api,web}.md
but missed updating packages/cli/scripts/copy-assets.ts, which still
listed those paths in FILE_ASSETS. The post-tsc build:assets step
then failed with ENOENT on every CI run, breaking 'Build Packages
& Test' and 'Windows WSL CLI Test'.

Drop the FILE_ASSETS array entirely — only DIR_ASSETS (templates)
remains. Local build now passes.
Pass through code comments + jsdoc + type definitions for v2 leftovers
that knip + grep didn't catch.

### Deletions

- packages/core/src/deprecation.ts: v1\u2192v2 deprecation banner module.
  showDeprecationWarning() only fires for major===1 (we're on
  3.0.0-beta.0, so it never runs), and the banner copy still
  describes 'v2 introduces...' (Hono RPC, Vite HMR, createApp). No
  internal callers; the public exports were the banner itself plus
  isV1Package() which always returns false now.
- Drop the public exports from packages/core/src/index.ts.

### packages/core/src/services/queue/service.ts

Replace ~12 jsdoc examples that showed 'await ctx.queue.publish(...)'
with the v3-correct pattern using QueueClient from @agentuity/queue.
Also fix the misleading @internal comment on QueueStorageService that
claimed it was 'instantiated by the runtime; use ctx.queue instead'.

### packages/core/src/services/oauth/token-storage.ts

Update KeyValueTokenStorage example to instantiate KeyValueClient
explicitly instead of taking ctx.kv from the v2 agent context.

### packages/core/src/services/session/get.ts

Drop the deprecated 'EvalRun' type alias (replaced by SessionEvalRun
months ago, no remaining callers in v3 code).

### packages/core/src/env.d.ts

- Drop AGENTUITY_AUTH_SECRET / AGENTUITY_CLOUD_BASE_URL /
  AGENTUITY_BASE_URL: declared but never read; auth was removed.
- Drop AGENTUITY_GRAVITY_LOG_LEVEL: gravity isn't used on v3.
- Drop AUTH_TRUSTED_DOMAINS: declared but never read; auth was removed.
- Reword 'used by the runtime to authenticate API requests' (v2
  language) to 'used by the service clients'.

### packages/cli/test/typescript-errors.test.ts

The TS error formatter test used 'workbench' as a fixture identifier
to prove TS2353 errors render aligned. Rename to 'telemetry' so
it doesn't read like leftover v2 code.

Typecheck + lint clean across all 30 packages.
…ite stub

Three loosely-related v2 cleanup wins:

### Deprecate @agentuity/schema

Decision (#107): @agentuity/schema is a complete schema-validation library
(s.string/s.object/etc., 763 LOC) competing with Zod and Valibot. v3 uses
Zod throughout; @agentuity/schema has zero internal callers outside an
unused public API in @agentuity/server.

- Add 'deprecated' field to packages/schema/package.json so npm install
  surfaces the warning.
- Rewrite packages/server/src/schema.ts: drop the @agentuity/schema
  branch, keep only the Zod path. Inline a minimal JSONSchema type so
  the export shape stays the same.
- Drop @agentuity/schema from packages/server/package.json deps.
- Add packages/schema to knip.json ignoreWorkspaces (deprecated, not
  worth scanning).

Note: docs/ and examples/ still reference @agentuity/schema. The docs
rewrite is deferred (#105); examples/ is being deleted in this same
commit.

### Delete examples/

The 9 demo apps under examples/ all use createApp/createAgent from
@agentuity/runtime — patterns that throw on v3 (since @agentuity/runtime
is a deprecation stub). Apps:

  ai-sdk, events, lifecycle, services-keyvalue,
  sse, standalone-context, streaming, websocket

None were workspace members, none ran in CI, none built on v3. Replacing
them with v3-equivalent demos is its own piece of work; in the meantime
keeping broken examples in the repo is worse than not having them.

Drop 'examples/**' from knip.json (no longer needed since the directory
itself is gone).

### Delete tests/integration/integration-suite

Was a TODO stub since the v3 cleanup (#1397): a Hono app with five
'TODO: Use @agentuity/keyvalue client' route bodies. The intent was
end-to-end HTTP-wrapped service tests, but tests/services/<svc>/ now
covers that ground more directly with live-cloud smoke tests.

- Remove the package and its test file.
- Drop the 'Run integration-suite tests' step from
  package-smoke-test.yaml.
- Remove integration-suite-only scripts from tests/package.json
  (the 'typecheck', 'build', 'test' scripts that were just thin
  wrappers around it).
- Update README mentions in tests/, scripts/ and the build.yaml
  comment.

### Rewrite packages/migrate/README.md

The README only described v1\u2192v2 migration; v3 added a v2\u2192v3 mode in
code (auto-detected from package.json) but the README never caught up.
Full rewrite covering both modes, plus the chain mode (v1\u2192v3 in two
runs).

Typecheck + lint clean across all 28 packages.
Two small open todos cleaned up.

### Delete bootstrapRuntimeEnv from @agentuity/server (#117)

bootstrapRuntimeEnv() and its options type were exported from
@agentuity/server with zero v3 callers — the CLI never imported it,
nothing in packages/* used it, and @agentuity/migrate even has a
transform that *removes* calls to it from user code on v2→v3
migration.

Drop:
- packages/server/src/runtime-bootstrap.ts (the file)
- the export from packages/server/src/index.ts
- the entry from packages/server/AGENTS.md's structure tree

@agentuity/migrate's detect/transform code still mentions
'bootstrapRuntimeEnv' as a string literal — that's intentional, it
needs to recognise the v2 pattern in user code to strip it out.

### Drop workspace: protocol handling from migrate (#96)

When testing the v2→v3 migration against this monorepo's apps/docs
(which used 'workspace:*' deps internally), we added two temporary
'workspace:' branches to the version-detection logic. Real users
never see workspace: protocol in their package.json — they have
'^2.0.0', 'latest', or similar.

- packages/migrate/bin/migrate.ts: drop runtimeVersion.startsWith('workspace:')
  from the v2-to-v3 detection check.
- packages/migrate/src/detect-v3.ts: drop versionStr.startsWith('workspace:')
  from the outdated-packages check.

Typecheck clean across all 27 packages.
Both were public-API packages with zero tests. The e2e suite rewrite
(memory #108) calls them out as priority targets; this commit lands
the unit-test surface so the package smoke gate covers them too.

### @agentuity/hono — 11 tests

Covers the agentuity() middleware:
- Returns a Hono middleware function.
- Initializes services + telemetry singletons on first call.
- Reuses the singletons on subsequent calls (idempotent composition).
- Injects all 8 service clients + tracer/logger/meter into c.var so
  downstream handlers and middleware see them.
- resetServices() and reset() correctly tear down the singletons,
  and a subsequent agentuity() call rebuilds them.
- Telemetry config overrides are accepted without crashing.

Adds tsconfig.test.json + 'test' script to packages/hono.

### @agentuity/analytics — 12 tests

Covers the pure utilities in packages/analytics/src/util.ts:
- generateId(): non-empty, distinct on each call.
- safeStringify(): handles null/undefined/primitives/objects/arrays
  and circular references without throwing.
- stripQueryString(): strips query + fragment, preserves clean URLs,
  falls back to a substring split on un-parseable input.

DOM-dependent helpers (getVisitorId, getCachedGeo, fetchGeo) are
left for a later browser-test pass — would need happy-dom or similar.

Adds tsconfig.test.json + 'test' script to packages/analytics.

### packages/server/test/schema.test.ts

Drop the 'Agentuity schemas' describe block (5 tests). After the
previous commit removed @agentuity/schema support from
toJSONSchema(), those tests started failing because the function
now only handles Zod. Drop them; the remaining Zod tests + the
'Unknown schemas' fallback tests still cover the function's full
behaviour.

### root package.json

Extend test:packages to include hono and analytics so 'bun run all'
exercises them too.
@agentuity/local is queued for removal alongside @agentuity/runtime
in v3.1 (memory #120). Drop it from the knip workspaces config so
future cleanup passes don't bother scanning it.
knip-driven cleanup of exports that have zero callers in the
non-deferred codebase.

### packages/cli/src/auth.ts
- Drop isAuthenticated(). No callers in v3; the equivalent surface
  is getAuth() (returns AuthData | null) which callers already use
  directly.

### packages/cli/src/cache/

Drop these from cache/index.ts barrel + their definitions:
- getResourceRegion / setResourceRegion (already @deprecated, no
  callers — getResourceInfo/setResourceInfo cover both region
  and orgId).
- clearProjectCache (defined in project-cache.ts, exported, no
  callers).

deleteResourceRegion stays — it's used in cmd/cloud/{db,sandbox,storage}.

### packages/cli/src/build-report.ts
- Drop getGlobalCollector(). setGlobalCollector +
  clearGlobalCollector are used; getGlobalCollector wasn't.

### packages/analytics/src/util.ts
- Demote getCachedGeo / setCachedGeo from public exports to module-
  private helpers. They're only consumed by fetchGeo() in the same
  file.

### packages/analytics/src/config.ts
- Drop MAX_CUSTOM_EVENTS constant. Defined but never read anywhere
  in the package.

knip count: 131 \u2192 120 unused exports. Typecheck clean across all 27
packages.
Earlier commit deleted tests/integration/integration-suite/ but missed
updating the root typecheck:apps script, which still ran
'bun run --filter=./tests/integration/integration-suite typecheck'.
That filter now matches no packages, breaking 'Build Packages & Test'
in CI.

Drop the integration-suite segment; the remaining three integration
apps (standalone-backend, e2e-web, oauth) cover the typecheck pass.
- Switch service/db templates from drizzle-orm/neon-serverless to
  drizzle-orm/neon-http (neon() is the HTTP driver; neon-serverless
  expects a Pool/Client). Affects nextjs, nuxt, remix, sveltekit,
  astro, hono, vite-react.
- Switch service/storage templates from s3.file(k).write(body, opts)
  to s3.write(k, body, opts). S3FileLike has no write(); write lives
  on S3ClientLike. Affects all 7 framework templates and snippets.
@agentuity/storage now ships bucketConfigFromEnv(env?), which builds
a BucketConfig from environment variables. It prefers the canonical
AGENTUITY_BUCKET_* names and falls back to AWS_* (AWS_ENDPOINT +
AWS_BUCKET + AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY) when those
aren't set. The fallback matches what the platform currently injects
when a bucket is provisioned (host + bucket as separate vars) and
should be removed once infra emits AGENTUITY_BUCKET_* directly.

To support the AWS form, BucketConfig now accepts either a single
`endpoint` (virtual-hosted-style) or separate `host` + `bucket`
fields, with a shared resolveEndpoint() helper used by both backends.
Existing `endpoint`-only callers keep working unchanged.

The storage templates for all 7 frameworks now just call
`createS3Client(bucketConfigFromEnv())` behind a lazy getS3()
singleton. The lazy wrapper avoids module-load throws during
build-time static analysis (Next.js' page-data collection step
crashes if the s3 client is constructed at import time without env
vars present).
Brings in the AI Gateway SDK + CLI commands and the standalone Pi
plugin (PRs #1451 and #1453 from main), aligning them with v3
conventions:

- @agentuity/aigateway client (uses @agentuity/adapter, not /server)
- @agentuity/pi plugin (depends on aigateway + adapter, hooked into
  coder-tui)
- agentuity cloud aigateway models|complete CLI commands, ported to
  Node-compatible APIs (node:fs, node:sqlite shim, readStdinText)
- AI Gateway URL added to getServiceUrls() in core + server
- @agentuity/core/aigateway subpath export
- Docs: AI Gateway API reference page + nav entries
- Coder workspace create gains --dependency / --setup-script /
  --system-prompt support (with shared common.ts helpers)
- Coder skill create custom subcommand

Also fixes two pre-existing test isolation bugs surfaced by the new
suites:

- packages/test-utils mockFetch() now auto-restores via
  onTestFinished, plus a restoreFetch() helper. The previous
  implementation leaked the mock across files.
- packages/opencode sqlite test no longer uses
  file:NAME?mode=memory&cache=shared URIs (bun:sqlite ignores URI
  flags by default and was creating literal on-disk files in the repo
  root). Switched to real temp-file paths with cleanup.

Skipped from main: apps/ tree, templates/, and the v2-era
dev/index.ts gravity rewrite. Versions bumped to 3.0.0-beta.2 to
match the v3 release line.
@agentuity/schema's `.pick(keys)` / `.omit(keys)` accepts a string
array, but zod 4 only accepts the object/mask form
`.pick({ a: true, b: true })`. The migrate chain test surfaced this
on the standard v1 scaffold's `src/api/index.ts`, which uses
`TranslateOutput.pick(['history', 'threadId', 'translationCount'])`
— after translation the file no longer typechecks.

Adds a new step in the schema-to-zod transform that rewrites
`.pick([...])` / `.omit([...])` call sites whose sole argument is a
literal array of string literals into the mask form. Calls with
non-literal arguments (a variable, a spread, mixed types) are
flagged with a TODO and left untouched so the user can hand-
translate them.

Also adds the package's first unit-test file
(packages/migrate/test/transforms/schema-to-zod.test.ts) covering
import swap, builder rewrites, infer rename, union variadic→array,
new pick/omit rewrites, the TODO fallthrough for non-literal args,
toJSONSchema stub, coerce builders, and bare-type-import drop.

The end-to-end migrate chain test (MIGRATE_CHAIN_TEST=1) now passes
all 4 stages including the post-migrate typecheck.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants